import sys
from openpyxl import load_workbook, Workbook
from math import ceil
sys.path.append("..")
from functional.utils import WEIGHT_ALLOCATOR_OF_ALGORITHM
from traceback import format_exc

def split_addr_str(addr):
	if addr == None or addr == "":
		return []
	author = addr.split(";")
	author = [i.split(",") if addr != None and addr != "" else [] for i in author]
	return author

def split_addr_str_bind_author(addr):
	if addr == None or addr == "":
		return []
	author = addr.split(";")
	author = [i.split("|") if addr != None and addr != "" else [] for i in author]
	return author

def flattern(addr_list):
	res = []
	for row in addr_list:
		for specific in row:
			res.append([specific])
	return res

def count_single_addr(author_list, year, data_list, data_names, contribute, weight_allocator):
	len_author = len(author_list)
	author_weight = weight_allocator.get_weights(len_author)

	for i in range(0, len(data_names)):
		data_name = data_names[i]
		data_val = data_list[i]

		cnt = 0
		for author in author_list:
			len_coll = len(author)
			contri_per_coll = data_val * author_weight[cnt] / len_coll
			for coll in author:
				if coll == "":
					continue
				if not coll in contribute[data_name]:
					contribute[data_name][coll] = {}
				if not year in contribute[data_name][coll]:
					contribute[data_name][coll][year] = contri_per_coll
				else:
					contribute[data_name][coll][year] += contri_per_coll
			cnt += 1

# contribute结构：contribute[统计类型][学院][年份] = float
def count_contribute(sh, data_cols, row_from, row_to, addr_cols, year_col, count_mode, signal):
	contribute = {}
	for addr in addr_cols:
		addr_name = addr[0]
		contribute[addr_name] = {data[0] : {} for data in data_cols}
		contribute[addr_name]["发文"] = {}

	data_names = ["发文"]
	data_names.extend([data_col[0] for data_col in data_cols])

	years = set()

	length = row_to - row_from + 1
	step = ceil(length*0.1)

	for addr in addr_cols:
		addr_name = addr[0]
		input_col = addr[1]
		bind_author_flag = addr[2]
		algo_id = addr[3]
		weight_allocator = WEIGHT_ALLOCATOR_OF_ALGORITHM[algo_id]

		for i in range(row_from, row_to+1):
			try:
				addr_str = sh.cell(i, input_col).value
				year = sh.cell(i, year_col).value

				years.add(year)

				data_list = [1]
				data_list.extend([sh.cell(i, data_col[1]).value for data_col in data_cols])

				if bind_author_flag:
					addr_list = split_addr_str_bind_author(addr_str)
				else:
					addr_list = split_addr_str(addr_str)

				if count_mode == "college":
					addr_list = flattern(addr_list)

				count_single_addr(addr_list, year, data_list, data_names, contribute[addr_name], weight_allocator)
			
				cnt = i - row_from + 1
				if cnt % step == 0:
					signal.emit(f"{cnt/length*100:.2f}%")
			except Exception as e:
				e.args = (f"{e.args[0]}在处理行{i}的数据时",)
				raise e

	return contribute, years

def dump_data(sh, contribute_of_data, years):
	base_i = 3
	base_j = 3

	years = list(years)
	years.sort()

	sh.cell(2, 2).value = "学院"
	for j, year in enumerate(years):
		sh.cell(2, base_j+j).value = year
	sh.cell(2, base_j+len(years)).value = "总和"

	for cnt_i, coll in enumerate(contribute_of_data):
		this_i = base_i + cnt_i
		this_sum = 0
		sh.cell(this_i, 2).value = coll
		
		for cnt_j, year in enumerate(years):
			this_j = base_j + cnt_j
			if year in contribute_of_data[coll]:
				sh.cell(this_i, this_j).value = contribute_of_data[coll][year]
				this_sum += contribute_of_data[coll][year]

		sh.cell(this_i, base_j+len(years)).value = this_sum

def dump_contribute(contribute, output_file_name, years):
	wb = Workbook()
	del wb["Sheet"]


	addr_names = list(contribute.keys())
	addr_names.sort()
	
	for addr_name in addr_names:
		data_names = list(contribute[addr_name].keys())
		data_names.sort()

		for data_name in data_names:
			sh = wb.create_sheet(f"{addr_name}_{data_name}")
			dump_data(sh, contribute[addr_name][data_name], years)

	wb.save(output_file_name)

def count_func(args):
	try:
		workbook_file_name = args[0]
		output_file_name = args[1]
		sheet_name = args[2]
		row_from = args[3]
		row_to = args[4]
		data_cols = args[5]
		year_col = args[6]
		addr_cols = args[7]
		count_mode= args[8]
		signal = args[9]
		signal.emit("启动贡献统计任务\n开始加载EXCEL文件")

		wb = load_workbook(workbook_file_name)
		signal.emit("完成EXCEL文件加载\n开始统计贡献")
		sh = wb[sheet_name]

		contribute, years = count_contribute(sh, data_cols, row_from, row_to, addr_cols, year_col, count_mode, signal)

		signal.emit("完成贡献统计\n开始写入结果")
		dump_contribute(contribute, output_file_name, years)
		signal.emit("完成结果写入")

	except Exception as e:
		signal = args[9]
		signal.emit(f"统计失败：{e}\n追踪信息：{format_exc()}")

if __name__ == "__main__":
	addr_list = split_addr_str(input())
	name_list = split_addr_str_bind_author(input())
	print(addr_list)
	print(flattern(addr_list))
	print(name_list)
	print(flattern(name_list))